﻿namespace Vibstudio.NetConfigurator.Engine.Validation
{
    #region Namespaces

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Xml.Linq;

    using Vibstudio.NetConfigurator.Common;
    using Vibstudio.NetConfigurator.Engine;
    using Vibstudio.NetConfigurator.Exceptions;
    using Vibstudio.NetConfigurator.Globalization;
    using Vibstudio.NetConfigurator.Model;

    #endregion

    public class HttpValidator : IValidation<ConfigurationUrl>
    {
        #region Fields

        private readonly string _rootPath;

        #endregion

        #region Ctor(s)

        public HttpValidator(string rootPath)
        {
            _rootPath = rootPath;
        }

        #endregion

        #region Public Methods and Operators

        public List<ResultValidation<ConfigurationUrl>> Validate()
        {
            if (string.IsNullOrEmpty(_rootPath))
            {
                return new List<ResultValidation<ConfigurationUrl>>
                           {
                               new InvalidResultValidation<ConfigurationUrl>(ConfigurationUrl.CreateUnknownUrl(),
                                                                             Labeler.Get.BasePathNotSpecified.ToString())
                           };
            }

            return GetResultValidation(_rootPath);
        }

        public void Reset()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Methods

        private List<ResultValidation<ConfigurationUrl>> GetResultValidation(string rootPath)
        {
            try
            {
                var result = new List<ResultValidation<ConfigurationUrl>>();

                IDictionary<Application, List<string>> applicationSettings = ConfigurationHelper.GetApplicationSettings();

                foreach (KeyValuePair<Application, List<string>> valuePair in applicationSettings)
                {
                    //if (valuePair.Value.Contains("http"))
                    //{
                    List<string> fileList = ConfigurationHelper.GetFilesRecursively(rootPath, valuePair.Key);
                    try
                    {
                        if (fileList.Count <= 0)
                        {
                            throw new FileNotFoundException(ConfigurationHelper.ConfigurationFileName(valuePair.Key),
                                                            rootPath,
                                                            valuePair.Key.ID);
                        }

                        string filePath = fileList[0];

                        XDocument document = XDocument.Load(filePath);

                        IEnumerable<XAttribute> attributes =
                            from e in document.Elements().Descendants().Attributes()
                            where e.Value.StartsWith("http")
                            select e;

                        foreach (XAttribute attribute in attributes)
                        {
                            CheckUri(valuePair, result, attribute.Value);
                        }

                        IEnumerable<XElement> elements =
                            from e in document.Elements().Descendants()
                            where e.Name == "value" && e.Value.StartsWith("http")
                            select e;

                        foreach (XElement element in elements)
                        {
                            CheckUri(valuePair, result, element.Value);
                        }
                    }
                    catch (Exception exception)
                    {
                        result.Add(new ResultValidation<ConfigurationUrl>(valuePair.Key.ID,
                                                                            ConfigurationUrl.CreateUnknownUrl(),
                                                                            false,
                                                                            exception.Message));
                    }
                    //}
                }

                return result;
            }
            catch (Exception exception)
            {
                return new List<ResultValidation<ConfigurationUrl>>
                           {
                               new InvalidResultValidation<ConfigurationUrl>(ConfigurationUrl.CreateUnknownUrl(),
                                                                             exception.Message)
                           };
            }
        }

        private static void CheckUri(KeyValuePair<Application, List<string>> valuePair,
                                     List<ResultValidation<ConfigurationUrl>> result,
                                     string uri)
        {
            HttpWebResponse response = null;

            try
            {
                var request = (HttpWebRequest)WebRequest.Create(uri);
                request.Proxy = null;
                request.KeepAlive = false;

                response = (HttpWebResponse)request.GetResponse();

                result.Add(new ResultValidation<ConfigurationUrl>(
                               valuePair.Key.ID,
                               ConfigurationUrl.CreateUrl(uri)));
            }
            catch
            {
                result.Add(new ResultValidation<ConfigurationUrl>(
                               valuePair.Key.ID,
                               ConfigurationUrl.CreateUrl(uri),
                               false,
                               Labeler.Get.InvalidURI.ToString()));
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
        }

        #endregion
    }
}